package br.com.rhinovet.faces;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.ViewScoped;

import org.primefaces.context.RequestContext;
import org.primefaces.event.SelectEvent;

import br.com.rhinovet.entidade.Animal;
import br.com.rhinovet.entidade.Especie;
import br.com.rhinovet.entidade.Proprietario;
import br.com.rhinovet.entidade.Raca;
import br.com.rhinovet.enumgeral.PorteAnimal;
import br.com.rhinovet.enumgeral.Sexo;
import br.com.rhinovet.logica.contract.DefaultLogicaContract;
import br.com.rhinovet.util.DataUtil;
import br.com.rhinovet.util.FacesUtil;
import br.com.rhinovet.util.StringUtil;

@ManagedBean(name="animalFaces")
@ViewScoped
public class AnimalFaces extends FacesUtil {
	
	private static final long serialVersionUID = 1L;

	@ManagedProperty(value = "#{logicaDefault}")
	private DefaultLogicaContract<Animal> logicaAnimal;
	
	@ManagedProperty(value = "#{logicaDefault}")
	private DefaultLogicaContract<Especie> logicaEspecie;
	
	@ManagedProperty(value = "#{logicaDefault}")
	private DefaultLogicaContract<Proprietario> logicaProprietario;
	
	@ManagedProperty(value = "#{logicaDefault}")
	private DefaultLogicaContract<Raca> logicaRaca;
	
	private Animal animal = new Animal();
	private List<Animal> listaAnimal = new ArrayList<>();
	private String animalBusca;
	
	private List<Especie> listaEspecie = new ArrayList<>();
	private List<Proprietario> listaProprietario = new ArrayList<>();
	private List<Raca> listaRaca = new ArrayList<>();
	
	protected Proprietario proprietario = null;
	
	public AnimalFaces() {
		Proprietario proprietario = (Proprietario) getSession().getAttribute("proprietarioConsulta");
		if (proprietario != null) {
			this.proprietario = proprietario;
		}
	}
	
	@PreDestroy
	public void finalizar() {
		getSession().setAttribute("proprietarioConsulta", null);
		getSession().setAttribute("isPopup", null);
	}
	
	@PostConstruct
	protected void init() {
		this.buscarAnimal();
	}
	
	public void adicionar() {
		try {
			if (validaCampos()) {
				logicaAnimal.adicionar(animal);
				adicionarMensagem("Animal adicionado com sucesso");
				this.buscarAnimal();
				fecharModal("dialogAnimal");
			} else {
				return;
			}
			
		} catch (Exception e) {
			adicionarMensagem("Houve um erro ao adicionar a Animal");
		}
	}
	
	public void prepararAdicionar() {
		this.animal = new Animal();
		
		if (this.proprietario != null) {
			this.animal.setProprietario(this.proprietario);
		}
		
		abrirModal("dialogAnimal");
	}
	
	public void selecionarRegistro(Long idArea, boolean editar, boolean isPopup) {
		try {
			this.animal = logicaAnimal.obterPorId(Animal.class,idArea);
			this.calcularAnosMeses();
			
			if (editar) {
				abrirModal("dialogAnimal");
			} else {
				abrirModal("dialogExcluir");
			}
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public void editar() {
		try {
			if (validaCampos()) {
				logicaAnimal.editar(this.animal);
				adicionarMensagem("Animal editado com sucesso");
				fecharModal("dialogAnimal");
				this.buscarAnimal();
			} else {
				return;
			}
			
		} catch (Exception e) {
			adicionarMensagem("Houve um erro ao editar a Animal");
		}
	}
	
	public void remover() {
		try {
			logicaAnimal.remover(Animal.class, this.animal.getId());
			adicionarMensagem("Animal removido com sucesso");
			fecharModal("dialogExcluir");
			this.buscarAnimal();
		} catch (Exception e) {
			adicionarMensagem("Houve um erro ao remover a Animal");
		}
	}
	
	public void buscarAnimal() {
		if (listaAnimal != null) {
			this.listaAnimal.clear();
		}
		try {
			String campoBuscaOrdenacao = "nome";
			if (this.proprietario != null) {
				this.listaAnimal =  this.logicaAnimal.buscarPorRelacionamento(Animal.class, "proprietario", this.proprietario.getId());
			} else if (StringUtil.textoPreenchido(animalBusca)) {
				this.listaAnimal = logicaAnimal.buscarPorCampo(Animal.class, campoBuscaOrdenacao, animalBusca, campoBuscaOrdenacao, null);
			} else {
				this.listaAnimal =  logicaAnimal.buscarTodos(Animal.class, campoBuscaOrdenacao, null);				
			}
		} catch (Exception e) {
			adicionarMensagem("Houve um erro ao buscar as informações");
		}
	}
	
	public boolean validaCampos() {
		boolean valido = true;
		
		if (!StringUtil.textoPreenchido(this.animal.getNome())) {
			adicionarMensagem("O campo nome é obrigatório");
			valido = false;
		}
		
		if (this.animal.getEspecie() == null) {
			adicionarMensagem("O campo espécie é obrigatório");
			valido = false;
		}
		
		if (this.animal.getProprietario() == null) {
			adicionarMensagem("O campo proprietário é obrigatório");
			valido = false;
		}
		
		if (this.animal.getEspecie() != null && this.animal.getEspecie().getExigeRaca() && this.animal.getRaca() == null) {
			adicionarMensagem("O campo raça é obrigatório");
			valido = false;
		}
		
		return valido;
	}
	
	public List<Animal> autoComplete(String query) {
		List<Animal> suggestions = new ArrayList<>();
		if (query.length() > 2) {
			try {
				suggestions = logicaAnimal.buscarPorCampo(Animal.class, "nome", query, "nome", null);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return suggestions;
    }
	
    public void retornoProprietario(SelectEvent event) {
        Proprietario proprietario = (Proprietario) event.getObject();
        this.animal.setProprietario(proprietario);
    }

    public void retornoEspecie(SelectEvent event) {
        Especie especie = (Especie) event.getObject();
        this.animal.setEspecie(especie);
        desabilitarDialog();
    }

    public void retornoRaca(SelectEvent event) {
        Raca raca = (Raca) event.getObject();
        this.animal.setRaca(raca);
        desabilitarDialog();
    }
    
    public List<Sexo> getListaSexo() {
    	List<Sexo> listaSexo = new ArrayList<>();
    	listaSexo.add(Sexo.FEMEA);
    	listaSexo.add(Sexo.MACHO);
    	return listaSexo;
    }
    
    public List<PorteAnimal> getListaPorte() {
    	List<PorteAnimal> listaPorte = Arrays.asList(PorteAnimal.values());
    	return listaPorte;
    }
    
    /**
     * Abre o Dialog de Espécie
     */
    public void selecionarEspecie() {
    	abrirDialogFramework("especie", true);
    }
    
    public void selecionarProprietario() {
    	abrirDialogFramework("proprietario", true);
    }

    public void selecionarRaca() {
    	abrirDialogFramework("raca", true);
    }

	
    /**
     * Abre o Dialog Framework
     */
    public void selecionarAnimal() {
    	abrirDialogFramework("animal", true);
    }
    
    /**
     * Fechar o Dialog Framework após seleção.
     * @param proprietario
     */
	public void selecionarNoDialog(Animal animal) {
        RequestContext.getCurrentInstance().closeDialog(animal);
    }
	
	public void calcularAnosMeses() {
		Date dataCalculo = animal.getDataFalecimento() == null ? new Date() : animal.getDataFalecimento();
		if (animal.getDataNascimento() != null) {
			Map<String, Integer> mapRetorno = DataUtil.diferencaAnoMes(this.animal.getDataNascimento(), dataCalculo);
			this.animal.setAno(mapRetorno.get("anos"));
			this.animal.setMeses(mapRetorno.get("meses"));
			this.animal.setDias(mapRetorno.get("dias"));
		}
	}
	
	public Animal getAnimal() {
		return animal;
	}

	public void setAnimal(Animal animal) {
		this.animal = animal;
	}

	public List<Animal> getListaAnimal() {
		return listaAnimal;
	}

	public void setListaAnimal(List<Animal> listaAnimal) {
		this.listaAnimal = listaAnimal;
	}

	public String getAnimalBusca() {
		return animalBusca;
	}

	public void setAnimalBusca(String animalBusca) {
		this.animalBusca = animalBusca;
	}

	public Proprietario getProprietario() {
		return proprietario;
	}

	public void setProprietario(Proprietario proprietario) {
		this.proprietario = proprietario;
	}

	public void setLogicaAnimal(DefaultLogicaContract<Animal> logicaAnimal) {
		this.logicaAnimal = logicaAnimal;
	}

	public List<Especie> getListaEspecie() {
		return listaEspecie;
	}

	public void setListaEspecie(List<Especie> listaEspecie) {
		this.listaEspecie = listaEspecie;
	}

	public void setLogicaEspecie(DefaultLogicaContract<Especie> logicaEspecie) {
		this.logicaEspecie = logicaEspecie;
	}

	public List<Proprietario> getListaProprietario() {
		return listaProprietario;
	}

	public void setListaProprietario(List<Proprietario> listaProprietario) {
		this.listaProprietario = listaProprietario;
	}

	public List<Raca> getListaRaca() {
		return listaRaca;
	}

	public void setListaRaca(List<Raca> listaRaca) {
		this.listaRaca = listaRaca;
	}

	public void setLogicaProprietario(
			DefaultLogicaContract<Proprietario> logicaProprietario) {
		this.logicaProprietario = logicaProprietario;
	}

	public void setLogicaRaca(DefaultLogicaContract<Raca> logicaRaca) {
		this.logicaRaca = logicaRaca;
	}
	
	
	
}